package com.gaxy.gateway.filter;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 登录拦截器
 *
 * @author Gaxy
 * @create 2024/06/20/上午 11:01
 */
@Component
@Slf4j
public class LoginFilter implements GlobalFilter {

    //目的是解析token，拿到loginId
    @SneakyThrows
    @Override
    //ServerWebExchange exchange: 代表整个HTTP请求-响应交互过程的上下文，包含请求、响应及其它交互信息
    //GatewayFilterChain chain: 过滤器链，调用chain.filter(exchange)会继续执行链中的下一个过滤器或最终到达目标服务。
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        //mutate方法允许在一个Builder对象上修改请求的各种属性，而不会直接影响到原始的对象
        //这里等于是复制了一个request对象的各种参数到mutate中，后面还要调用mutate.build()
        ServerHttpRequest.Builder mutate = request.mutate();
        //检查路径 如果是登录就放行
        String url = request.getURI().getPath();
        log.info("LoginFilter.filter.url:{}", url);
        if(url.equals("/user/doLogin")){
            chain.filter(exchange);
        }
        //将loginId放在request的header中
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        String loginId = (String) tokenInfo.getLoginId();
        if (StringUtils.isEmpty(loginId)){
            throw new Exception("未获取到用户信息");
        }
        mutate.header("loginId", loginId);
        //使用mutate()方法创建一个可变的交换器副本，使用request()方法将请求消息替换为新构建的请求消息，使用build()方法构建最终的交换器对象并返回
        return chain.filter(exchange.mutate().request(mutate.build()).build());
    }

}
